package org.metis4j.framework.mvc;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.metis4j.framework.core.helper.ClassHelper;
import org.metis4j.framework.mvc.annotation.Action;
import org.metis4j.framework.mvc.annotation.Request;
import org.metis4j.framework.mvc.bean.RequestBean;
import org.metis4j.framework.util.CollectionUtil;
import org.metis4j.framework.util.StringUtil;


public class ActionHelper {

	private static Map<RequestBean, Handler> actionMap = new HashMap<>();

	static {
		List<Class<?>> actionClassList=ClassHelper.getClassListByAnnotation(Action.class);
		if(CollectionUtil.isNotEmpty(actionClassList)){
			Map<RequestBean,Handler> commonActionMap=new HashMap<>();
			Map<RequestBean,Handler> regexpActionMap=new HashMap<>();
			for(Class<?> actionClass:actionClassList){
				Method[] actionMethods=actionClass.getDeclaredMethods();
				for(Method actionMethod:actionMethods){
					handleActionMothod(actionMethod,actionClass,commonActionMap,regexpActionMap);
				}
			}
			actionMap.putAll(commonActionMap);
			actionMap.putAll(regexpActionMap);
		}
		
	}

	private static void handleActionMothod(Method actionMethod, Class<?> actionClass, Map<RequestBean, Handler> commonActionMap,
			Map<RequestBean, Handler> regexpActionMap) {
		// TODO Auto-generated method stub
		if(actionClass.isAnnotationPresent(Request.Get.class)){
			String requestPath=actionMethod.getAnnotation(Request.Get.class).value();
			putActionMap("GET",actionMethod,requestPath,actionClass,commonActionMap,regexpActionMap);
		}else if(actionClass.isAnnotationPresent(Request.Post.class)){
			String requestPath=actionMethod.getAnnotation(Request.Post.class).value();
			putActionMap("POST",actionMethod,requestPath,actionClass,commonActionMap,regexpActionMap);
		}else if(actionClass.isAnnotationPresent(Request.Put.class)){
			String requestPath=actionMethod.getAnnotation(Request.Put.class).value();
			putActionMap("PUT",actionMethod,requestPath,actionClass,commonActionMap,regexpActionMap);
		}else{
			String requestPath=actionMethod.getAnnotation(Request.Delete.class).value();
			putActionMap("DELETE",actionMethod,requestPath,actionClass,commonActionMap,regexpActionMap);
		}
	}

	private static void putActionMap(String requestMethod, Method actionMethod, String requestPath, Class<?> actionClass,
			Map<RequestBean, Handler> commonActionMap, Map<RequestBean, Handler> regexpActionMap) {
		// TODO Auto-generated method stub
		if(requestPath.matches(".+\\{\\w\\}.*")){
			requestPath=StringUtil.replaceAll(requestPath, "\\{\\w+\\}", "(\\\\w+)");
			regexpActionMap.put(new RequestBean(requestMethod, requestPath), new Handler(actionClass, actionMethod));
		}else{
			commonActionMap.put(new RequestBean(requestMethod, requestPath), new Handler(actionClass, actionMethod));
		}
		
	}
	
	public static Map<RequestBean,Handler> getActionMap(){
		return actionMap;
	}
}
